package mi.payment.utils.transaction;

import android.content.Context;
import android.util.Base64;

import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;

import java.util.Map;

import lainey.ui.utils.LogUtil;
import mi.payment.Constant;
import mi.payment.MyApplication;
import mi.payment.admin.RKI;
import mi.payment.bean.db.TradeData;
import mi.payment.utils.AllianceUtil;
import mi.payment.utils.AsciiUtil;
import mi.payment.utils.ByteUtil;
import mi.payment.utils.CalculateMacUtil;
import mi.payment.utils.iso8583.EncodePackage;
import mi.payment.utils.iso8583.FieldConfig;
import mi.payment.utils.iso8583.FieldUtils;
import mi.payment.utils.iso8583.MsgField;
import mi.payment.utils.iso8583.Utils;
import mi.payment.utils.secure.TerminalSecure;

public class ConsumptionTask extends TransactionTask<TradeData, Void, TradeData> {

    private byte[] macBytes;

    protected ConsumptionTask(Context context) {
        super(context, true);
    }

    @Override
    protected void onBegin(TradeData[] params) {
        setCUPDebit(true);
        setDBStorage(true);
        tradeData = params[0];
        dbBean = tradeData.getPayDetail();
    }

    @Override
    protected TradeData appointResult() {
        super.appointResult();
        return tradeData;
    }

    @Override
    protected Map<String, MsgField> preAssembly() {
        return EncodePackage.preAssemblyBase("3020078020C11A04");
    }

    @Override
    protected byte[] changeAndAssembly(Map<String, MsgField> fieldMap) {
        dbBean.setTransType("22");
        dbBean.setProcessCode("000000");
        dbBean.TerminalDate = System.currentTimeMillis() / 1000;

        Map<String, MsgField> map = FieldUtils.fillEachFieldValue(fieldMap, tradeData);

        MsgField f024 = map.get("F024");
        f024.setDataStr("262");

        MsgField f035 = map.get("F035");
        if (f035 != null) {
            String track2 = tradeData.getCardInfo().getMAGCardInfo().getTrack2();
            track2 = track2.replaceAll("=", "D");
            f035.setDataStr(track2);
        }

        MsgField f048 = map.get("F048");
        if (f048 != null) {
            f048.setDataStr("      ");
        }

        MsgField f062 = map.get("F062");
        f062.setDataStr(dbBean.voucherNo);

        MsgField f057 = map.get("F057");
        if (f057 != null) {
            String value = getF057Value();
            f057.setDataStr(value);
            f057.setDataType(FieldConfig.SDK_8583_DATA_BIT);
        }

        byte[] sendBytes = EncodePackage.assembly(map, "0200", TerminalSecure.PROCESSREQUEST_NONE, "6002620000");
        if (map.get("F064") == null) {
            macBytes = CalculateMacUtil.calculateMAC(sendBytes);
        }

        return sendBytes;
    }

    private String getF057Value() {
        String track2 = tradeData.getCardInfo().getMAGCardInfo().getTrack2();
        LogUtil.e(Constant.TAG, "track2: " + track2);
        track2 = track2.length() + track2;
        if (track2.length() % 2 != 0) {
            track2 = track2 + "0";
        }
        track2 = track2.replaceAll("=", "D");
        String track2_encode250 = AllianceUtil.encode250(track2);
        LogUtil.e(Constant.TAG, "track2_encode250: " + track2_encode250);

        String randomNumber = "363933";

        String f048_value = "0006202020202020";
        String f048_value_encode250 = AllianceUtil.encode250(f048_value);
        LogUtil.e(Constant.TAG, "f048_value_encode250: " + f048_value_encode250);

        String isoMsgClear250Buf = randomNumber;
        isoMsgClear250Buf = isoMsgClear250Buf + "23" + track2_encode250 + "01";
        isoMsgClear250Buf = isoMsgClear250Buf + "30" + f048_value_encode250;

        LogUtil.e(Constant.TAG, "isoMsgClear250Buf: " + isoMsgClear250Buf);

        // 不是8的倍数补00
        byte[] bytes = ByteUtil.hexStr2Bytes(isoMsgClear250Buf);
        int var = bytes.length % 8;
        if (var != 0) {
            LogUtil.e(Constant.TAG, "is NOT multiple of 8 --> var: " + var);
            var = 8 - var;
            for (int i = 0; i < var; i++) {
                if (i + 1 == var) {
                    isoMsgClear250Buf += "0" + var;
                } else {
                    isoMsgClear250Buf += "00";
                }
            }
            LogUtil.e(Constant.TAG, "padding isoMsgClear250Buf: " + isoMsgClear250Buf);
        }

        byte[] dataIn = ByteUtil.hexStr2Bytes(isoMsgClear250Buf);
        byte[] dataOut = new byte[dataIn.length];
        byte[] ivByte = ByteUtil.hexStr2Bytes("0000000000000000");
        try {
            int result = MyApplication.getInstance().mSecurityOptV2.dataEncrypt(Constant.indexDEK, dataIn,
                    AidlConstantsV2.Security.DATA_MODE_CBC, ivByte, dataOut);
            LogUtil.e(Constant.TAG, "result: " + result);

            String hexStr = ByteUtil.bytes2HexStr(dataOut);
            LogUtil.e(Constant.TAG, "hexStr: " + hexStr);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String encodeToString = Base64.encodeToString(dataOut, Base64.NO_WRAP);
        LogUtil.e(Constant.TAG, "encodeToString: " + encodeToString);

        String toAscii = AsciiUtil.stringToAscii(encodeToString);
        LogUtil.e(Constant.TAG, "toAscii: " + toAscii);

        String f057_value = "3031" + RKI.getTleKid() + "3031" + "3033" + "34" + "34" + "3031" + RKI.counter + toAscii;

        return f057_value;
    }

    @Override
    public byte[] regroupPackPreSend(byte[] sendBytes) {
        String log = "重组之前：" + Utils.byte2HexStr(sendBytes);
        LogUtil.e(Constant.TAG, log);

        Map<String, MsgField> requestMap = EncodePackage.preAssemblyBase("3020078000C01A85");
        byte[] newSendBytes = changeAndAssembly(requestMap);

        byte[] outBytes = new byte[newSendBytes.length - 6];
        // copy tPdu
        System.arraycopy(newSendBytes, 2, outBytes, 2, 5);

        // copy body
        System.arraycopy(newSendBytes, 13, outBytes, 7, newSendBytes.length - 13);

        // copy mac
        System.arraycopy(macBytes, 0, outBytes, outBytes.length - 8, 8);

        int hig = (outBytes.length - 2) / 256;
        int low = (outBytes.length - 2) % 256;
        outBytes[0] = (byte) hig;
        outBytes[1] = (byte) low;

        log = "重组之后:" + Utils.byte2HexStr(outBytes);
        LogUtil.e(Constant.TAG, log);

        return outBytes;
    }

    @Override
    public byte[] regroupPackOnResponse(byte[] receiveBytes) {
        String log = "重组之前:" + Utils.byte2HexStr(receiveBytes);
        LogUtil.e(Constant.TAG, log);

        byte[] outBytes = new byte[receiveBytes.length + 6];

        byte[] headBytes = Utils.hexStr2Bytes("888888888888");

        System.arraycopy(receiveBytes, 0, outBytes, 0, 7);
        System.arraycopy(headBytes, 0, outBytes, 7, headBytes.length);
        System.arraycopy(receiveBytes, 7, outBytes, 13, receiveBytes.length - 7);

        log = "重组之后:" + Utils.byte2HexStr(outBytes);
        LogUtil.e(Constant.TAG, log);

        return outBytes;
    }


}